<?php
/**
 * Created by PhpStorm.
 * User: dong
 * Date: 2018/3/6
 * Time: 1:52
 */
namespace App\Services\ThirdPayments\Recharge;

use App\Lib\PaymentMap;
use App\Lib\ThirdPartyMap;
use App\Models\RechargeOrder;
use App\Services\ThirdPayments\BankTraits\ECPSSBankMap;
use App\Services\ThirdPayments\Contracts\Actions\HtmlPrintAction;
use App\Services\ThirdPayments\Contracts\RechargeBaseAbstract;
use App\Services\ThirdPayments\Contracts\WAPable;
use Carbon\Carbon;
use Illuminate\Support\HtmlString;

class TYFPayment extends RechargeBaseAbstract implements WAPable
{
    use ECPSSBankMap;

    protected $gw_pay = 'http://cashier.fengyinchess.com/cgi-bin/netpayment/pay_gate.cgi';
    protected $gw_query = 'http://cashier.fengyinchess.com/cgi-bin/netpayment/pay_gate.cgi';

    protected $orderStatusArr = [
        '0' => '未支付',
        '1' => '成功',
        '2' => '失败',
        '4' => '部分退款',
        '5' => '全额退款',
        '9' => '退款处理中',
        '10' => '未支付',
        '11' => '订单过期'
    ];

    public function callback(array $data)
    {
        // TODO: Implement callback() method.
        if ($this->veryCallbackSign($data) && $data['notifyType'] == '1') {
            if ($data['orderStatus'] == '1') {
                return true;
            }
        }
        return false;
    }

    public function veryCallbackSign(array $data)
    {
        // TODO: Implement veryCallbackSign() method.
        $signStr = 'apiName=' . $data['apiName'] . '&';
        $signStr .= 'notifyTime=' . $data['notifyTime'] . '&';
        $signStr .= 'tradeAmt=' . $data['tradeAmt'] . '&';
        $signStr .= 'merchNo=' . $data['merchNo'] . '&';
        $signStr .= 'merchParam=' . $data['merchParam'] . '&';
        $signStr .= 'orderNo=' . $data['orderNo'] . '&';
        $signStr .= 'tradeDate=' . $data['tradeDate'] . '&';
        $signStr .= 'accNo=' . $data['accNo'] . '&';
        $signStr .= 'accDate=' . $data['accDate'] . '&';
        $signStr .= 'orderStatus=' . $data['orderStatus'];
        $signStr .= $this->getMchKey();
        if (strcasecmp(md5($signStr), $data['signMsg']) == 0) {
            return true;
        }
        return false;
    }

    public function getOrderNoFromCallback(array $data)
    {
        // TODO: Implement getOrderNoFromCallback() method.
        return $data['orderNo'];
    }

    public function getOrderAmtFromCallback(array $data)
    {
        // TODO: Implement getOrderAmtFromCallback() method.
        return $data['tradeAmt'];
    }

    /**
     * @return mixed
     */
    public function getIdentify(): string
    {
        // TODO: Implement getIdentify() method.
        return ThirdPartyMap::TYFPay;
    }

    /**
     *  needs child to achieve
     */
    public function initPaymentMap(): array
    {
        // TODO: Implement initPaymentMap() method.
        return [
            PaymentMap::BANK => 1,
            PaymentMap::ALI => 4,
            PaymentMap::WX => 5,
            PaymentMap::QQ => 6,
            PaymentMap::WX_WAP => 11,
            PaymentMap::ALI_WAP => 10,
            PaymentMap::BANK_WAP => 17,
            PaymentMap::QQ_WAP => 6
        ];
    }

    public function query(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement query() method.
        $this->setParameter('apiName', 'MOBO_TRAN_QUERY');
        $this->setParameter('apiVersion', '1.0.0.0');
        $this->setParameter('platformID', $this->getMchId());
        $this->setParameter('merchNo', $this->getMchId());
        $this->setParameter('orderNo', $rechargeOrder->plat_no);
        $this->setParameter('tradeDate', Carbon::parse($rechargeOrder->created_at)->format('Ymd'));
        $this->setParameter('amt', $rechargeOrder->order_amt);
        $this->setParameter('signMsg', $this->querySign());

        try {

            $res = curlHttp($this->getGwQuery(), $this->getParameters(), 'post');
            if ($res['http_code'] == 200) {
                $resultData = $res['body'];
                preg_match('{<respCode>(.*?)</respCode>}', $resultData, $match);
                $respCode = $match[1];
                preg_match('{<respDesc>(.*?)</respDesc>}', $resultData, $match);
                $respDesc = $match[1];
                preg_match('{<Status>(.*?)</Status>}', $resultData, $match);
                $respStatus = count($match) > 1 ? $match[1] : '0';
                if ($respCode === '00') {
                    if (count($match) > 1) {
                        if ($respStatus == '1') {
                            return true;
                        }
                        return $this->orderStatusArr[(string)$respStatus];
                    }
                }
                return convertToUTF8($respDesc);
            }
            return $res['body'];
        } catch (\Exception $exception) {
            return $exception->getMessage();
        }
    }

    public function bankHref(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement bankHref() method.
        $this->initParameters($rechargeOrder);
        $content = formPostHtml($this->getGwPay(), $this->getParameters());
        return new HtmlPrintAction(new HtmlString($content));
    }

    public function scanCode(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement scanCode() method.
        $this->initParameters($rechargeOrder);
        $content = formPostHtml($this->getGwPay(), $this->getParameters());
        return new HtmlPrintAction($content);
    }

    public function paySign(): string
    {
        // TODO: Implement paySign() method.
        $sign = 'apiName=' . $this->getParameter('apiName') . '&';
        $sign .= 'apiVersion=' . $this->getParameter('apiVersion') . '&';
        $sign .= 'platformID=' . $this->getParameter('platformID') . '&';
        $sign .= 'merchNo=' . $this->getParameter('merchNo') . '&';
        $sign .= 'orderNo=' . $this->getParameter('orderNo') . '&';
        $sign .= 'tradeDate=' . $this->getParameter('tradeDate') . '&';
        $sign .= 'amt=' . $this->getParameter('amt') . '&';
        $sign .= 'merchUrl=' . $this->getParameter('merchUrl') . '&';
        $sign .= 'merchParam=' . $this->getParameter('merchParam') . '&';
        $sign .= 'tradeSummary=' . $this->getParameter('tradeSummary');
        $sign .= $this->getMchKey();
        return md5($sign);
    }

    public function querySign(): string
    {
        // TODO: Implement querySign() method.
        $sign = 'apiName=' . $this->getParameter('apiName') . '&';
        $sign .= 'apiVersion=' . $this->getParameter('apiVersion') . '&';
        $sign .= 'platformID=' . $this->getParameter('platformID') . '&';
        $sign .= 'merchNo=' . $this->getParameter('merchNo') . '&';
        $sign .= 'orderNo=' . $this->getParameter('orderNo') . '&';
        $sign .= 'tradeDate=' . $this->getParameter('tradeDate') . '&';
        $sign .= 'amt=' . $this->getParameter('amt');
        $sign .= $this->getMchKey();
        return md5($sign);
    }

    public function showSuccess(): string
    {
        // TODO: Implement showSuccess() method.
        return 'SUCCESS';
    }

    public function initParameters(RechargeOrder $rechargeOrder)
    {
        $mchData = $rechargeOrder->order_data;
        // TODO: Implement initParameters() method.
        if (PaymentMap::isWapReq($mchData['recharge_type'])) {
            $apiName = 'WAP_PAY_B2C';
        } else {
            $apiName = 'WEB_PAY_B2C';
        }
        $this->setParameter('apiName', $apiName);
        $this->setParameter('apiVersion', '1.0.0.0');
        $this->setParameter('platformID', $this->getMchId());
        $this->setParameter('merchNo', $this->getMchId());
        $this->setParameter('orderNo', $rechargeOrder->plat_no);
        $this->setParameter('tradeDate', Carbon::now()->format('Ymd'));
        $this->setParameter('amt', $rechargeOrder->order_amt);
        $this->setParameter('merchUrl', $this->getCallbackUrl());
        $this->setParameter('merchParam', $this->setRemark($rechargeOrder));
        $this->setParameter('tradeSummary', $mchData['body']);
        $this->setParameter('signMsg', $this->paySign());
        if (PaymentMap::isBankHref($mchData['recharge_type'])) {
            $this->setParameter('bankCode', $this->getBank($mchData['bank_code']));
        }
        $this->setParameter('choosePayType', $this->getPaymentMap($mchData['recharge_type']));
    }

    public function wapReq(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement wapReq() method.
        $this->initParameters($rechargeOrder);
        $content = formPostHtml($this->getGwPay(), $this->getParameters());
        return new HtmlPrintAction(new HtmlString($content));
    }

    public function isReturnInCallback(array $data)
    {
        return $data['notifyType'] == '1' ? false : true;
    }
}
